package javavis.jip3d.functions;

import javavis.base.Function3DGroup;
import javavis.base.JIPException;
import javavis.base.ParamType;
import javavis.jip3d.gui.Function3D;
import javavis.jip3d.gui.FunctionParam;
import javavis.jip3d.gui.ScreenData;
import javavis.jip3d.gui.ScreenOptions;
import javavis.jip3d.gui.dataobjects.NeuronSet3D;
import javavis.jip3d.gui.dataobjects.PlaneSet3D;
import javavis.jip3d.gui.dataobjects.PointSet3D;
import javavis.jip3d.gui.dataobjects.Trajectory;
import javavis.jip3d.gui.dataobjects.Trajectory3D;

/**
 * Clase FProcessTrajSR4K
 * @author dviejo
 *
 * Procesa una trayectoria en la que cada pose incluye datos de un mapa de neuronas sobre datos 3D
 * Los ficheros de datos con los puntos 3D originales se han de incorporar a la trayectoria antes de los
 * ficheros de neuronas. Por ejemplo:
 * 		;100 #numero de puntos
 * 		;seq0000.p3d 0 0 0 0 0 0
 * 		;seq0000_2000p_2000n.map 0 0 0 0 0 0
 * 		;seq0001.p3d 0 0 0 0 0 0
 * 		;seq0001_2000p_2000n.map 0 0 0 0 0 0
 * 		; etc.
 */
public class FProcessTrajSR4K extends Function3D {

	public FProcessTrajSR4K()
	{
		super();

		this.allowed_input = ScreenOptions.tTRAJ2D | ScreenOptions.tTRAJ3D;
		this.group = Function3DGroup.Model3D;
		FunctionParam p0 = new FunctionParam("Check Integrity", ParamType.BOOL);
		p0.setValue(false);
		
		FunctionParam p1 = new FunctionParam("Input", ParamType.FILE); //fichero con la trayectoria de p3d

		FunctionParam p2 = new FunctionParam("Output", ParamType.DIR);

		this.addParam(p0);
		this.addParam(p1);
		this.addParam(p2);
//		this.addParam(p3);
	}
	@Override
	public void proccessData(ScreenData scrData) throws JIPException {
		String ruta_planos = this.paramValueString("Output");
		String file_name, path;
		int file_number, cont;
		Trajectory traj;
		
		boolean checkIntegrity = paramValueBool("Check Integrity");
		
		Trajectory trajPoints = null;
		String pointTraj = "";
		String pointPath = "";
		if(checkIntegrity)
		{
			trajPoints = new Trajectory3D(new ScreenOptions());
			pointTraj = paramValueString("Input");
			pointPath = pointTraj.substring(0, pointTraj.lastIndexOf('/')+1);
			trajPoints.readData(pointTraj.substring(pointTraj.lastIndexOf('/')+1), pointPath);
		}

		long total_time, t1, t2;
		int total_planes, total_points;
		NeuronSet3D neurons;
		PlaneSet3D planes;

		FPPatchSR4K seg_planos = new FPPatchSR4K();
		seg_planos.setParamValue("Check integrity", checkIntegrity);
		seg_planos.setParamValue("Neighbor gen", 3);
		seg_planos.setParamValue("PlaneThick", 0.035);
		PointSet3D points;
		
		total_time = 0;
		total_planes = 0;
		total_points = 0;
		traj = (Trajectory)scrData;
		if(checkIntegrity && trajPoints.files.size() < traj.files.size()) throw new JIPException("Error: p3d and GNG have different sizes");
		file_number = traj.files.size();
		double prog_inc = 100.0 / file_number;
		path = traj.path;

		for(cont=0;cont<file_number;cont++)
		{
			//pointSet3D 
			if(checkIntegrity)
			{
				file_name = trajPoints.files.get(cont);
				points = new PointSet3D(new ScreenOptions());
				points.readData(file_name, pointPath);
				seg_planos.setParamValue("Source PointSet", points);
			}

			//neuronSet3D
			file_name = traj.files.get(cont);
			System.out.println("File "+cont+" - "+path+file_name);
			neurons = new NeuronSet3D(new ScreenOptions());
			neurons.readData(file_name, path);
			total_points += neurons.scr_opt.num_points;

			t1 = System.currentTimeMillis();
			seg_planos.proccessData(neurons);
			t2 = System.currentTimeMillis();
			total_time += t2 -t1;
			planes = (PlaneSet3D)seg_planos.result_list.remove(0);
			total_planes += planes.scr_opt.num_points;
			planes.writeData(file_name, ruta_planos);
			progress += prog_inc;
		}
		System.out.println("Statistics:");
		System.out.println("Points per image (mean): "+total_points/file_number);
		System.out.println("Planes per image (mean):"+total_planes/file_number);
		System.out.println("Time for extracting planes per image (mean): "+total_time/file_number);
	}

}
